import { bindCallback, Observable } from 'rxjs';
import { Asset, assetManager, __private } from "cc";
import { sceneScheduler } from './schedule/creator';
import { AssetManager } from 'cc';

export function loadAssetByUUID(requests: string[]) {
    let selector = (err: Error, data: any) => { return { err, data }; }
    let bcb = bindCallback(assetManager.loadAny.bind(assetManager), selector, sceneScheduler);
    return bcb(requests);
}

export function loadBundle(bundleName) {
    let selector = (err: Error, data: any) => { return { err, data }; }
    let bcb = bindCallback(assetManager.loadBundle.bind(assetManager), selector, sceneScheduler);
    return bcb(bundleName);
}

export function bundlePreloadDir<T extends Asset>(
    bundleName: string,
    paths: string | string[],
    type: __private._types_globals__Constructor<T>,
    onProgress?: (finished: number, total: number, item: AssetManager.RequestItem) => void) {
    let bundle = assetManager.getBundle(bundleName);
    let selector = (err: Error, data: T) => { return { err, data }; }
    let bcb = bindCallback(bundle.preloadDir.bind(bundle), selector, sceneScheduler);
    return bcb(paths as any, type, onProgress);
}

export function bundlePreload<T extends Asset>(
    bundleName: string,
    paths: string | string[],
    type: __private._types_globals__Constructor<T>,
    onProgress?: (finished: number, total: number, item: AssetManager.RequestItem) => void) {
    let bundle = assetManager.getBundle(bundleName);
    let selector = (err: Error, data: T) => { return { err, data }; }
    let bcb = bindCallback(bundle.preload.bind(bundle), selector, sceneScheduler);
    return bcb(paths as any, type, onProgress);
}

export function bundlePreloadScene<T extends Asset>(
    bundleName: string,
    sceneName: string,
    onProgress?: (finished: number, total: number, item: AssetManager.RequestItem) => void) {
    let bundle = assetManager.getBundle(bundleName);
    let selector = (err: Error, sceneAsset: T) => { return { err, sceneAsset }; }
    let bcb = bindCallback(bundle.preloadScene.bind(bundle), selector, sceneScheduler);
    return bcb(sceneName, null, onProgress);
}

export function bundleLoadScene<T extends Asset>(
    bundleName: string,
    sceneName: string,
    onProgress?: (finished: number, total: number, item: AssetManager.RequestItem) => void) {
    let bundle = assetManager.getBundle(bundleName);
    let selector = (err: Error, sceneAsset: T) => { return { err, sceneAsset }; }
    let bcb = bindCallback(bundle.loadScene.bind(bundle), selector, sceneScheduler);
    return bcb(sceneName, null, onProgress);
}

// const { err, data } = await lastValueFrom(bundleLoad(this.assetbundleName, 'AudioSource', Prefab));
// if (err != null) {
//     this.warn('load audioSource prefab err', err);
//     return;
// }
// const node = instantiate<Node>(data);

export function bundleLoad<T extends Asset>(
    bundleName: string,
    paths: string | string[],
    type: __private._types_globals__Constructor<T>,
    onProgress?: (finished: number, total: number, item: AssetManager.RequestItem) => void) {
    let bundle = assetManager.getBundle(bundleName);
    let selector = (err: Error, data: T | T[]) => { return { err, data }; }
    let bcb = bindCallback(bundle.load.bind(bundle), selector, sceneScheduler);
    return bcb(paths as any, type, onProgress) as Observable<{ err: Error, data: T | T[] }>;
}

export function bundleRelease(bundleName: string, paths: string, type: __private._types_globals__Constructor<Asset> | null) {
    let bundle = assetManager.getBundle(bundleName);
    bundle?.release(paths, type);
}

export function bundleLoadDir<T extends Asset>(
    bundleName: string,
    paths: string | string[],
    type: __private._types_globals__Constructor<T>,
    onProgress?: (finished: number, total: number, item: AssetManager.RequestItem) => void) {
    let bundle = assetManager.getBundle(bundleName);
    let selector = (err: Error, data: T[]) => { return { err, data }; }
    let bcb = bindCallback(bundle.loadDir.bind(bundle), selector, sceneScheduler);
    return bcb(paths as any, type, onProgress) as Observable<{ err: Error, data: T[] }>;
}